/*
   Copyright (c) 2023 李伟国
   shiro-learner is licensed under Mulan PSL v2.
   You can use this software according to the terms and conditions of the Mulan PSL v2. 
   You may obtain a copy of Mulan PSL v2 at:
            http://license.coscl.org.cn/MulanPSL2 
   THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.  
   See the Mulan PSL v2 for more details. 
*/

package cn.learner.config.shiro;

import cn.learner.entity.Permission;
import cn.learner.entity.Role;
import cn.learner.entity.User;
import cn.learner.service.IPermissionService;
import cn.learner.service.IRoleService;
import cn.learner.service.IUserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

@Component
public class LearnerJdbcEmailRealm extends AuthorizingRealm {
    @Autowired
    private IUserService userService;
    @Autowired
    private IRoleService roleService;
    @Autowired
    private IPermissionService permissionService;
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        if(principals == null){
            throw new AuthorizationException("PrincipalCollection方法参数不能为空.");
        }
        String email = (String)this.getAvailablePrincipal(principals);
        Set<String> roleNameSet = new LinkedHashSet<>();  // 角色集合
        Set<String> permissionSet = new LinkedHashSet<>();  // 授权集合
        List<Role> roles = roleService.findByEmail(email);
        for(Role role: roles){
            roleNameSet.add(role.getName());
            List<Permission> permissionList = permissionService.findByRoleId(role.getId());
            for(Permission permission : permissionList){
                permissionSet.add(permission.getAuthorization());
            }
        }
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roleNameSet);
        info.setStringPermissions(permissionSet);
        return info;
    }


    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        String email = userToken.getUsername();
        if(email == null){
            throw new AccountException("此Realm不允许使用空用户名。");
        }
        SimpleAuthenticationInfo info = null;  // 认证信息
        String salt = null;
        String password = null;
        User userInfo = userService.findByEmail(email);
        if(userInfo == null){
            throw new UnknownAccountException("找不到用户的帐户 [" + email + "]");
        }else{
            password = userInfo.getPassword();
            salt = userInfo.getSalt();
            info = new SimpleAuthenticationInfo(email,password,this.getName());
            if(salt!=null){
                info.setCredentialsSalt(ByteSource.Util.bytes(salt));
            }
        }
        return info;
    }
}
